
import java.io.*;
import java.net.*;
import java.util.*;

class Server {

    public static final String ASK_FOR_WORK = "I CAN HAZ WORK?";
    public static final int populationSize = 30;

    public static void main(String args[]) throws Exception {
        List<String> toRun = new ArrayList();
        DatagramSocket serverSocket = new DatagramSocket(9876);
        List<Individual> population = new ArrayList();
        BufferedWriter stats = new BufferedWriter(new FileWriter(new File("antStats.txt")));
        BufferedWriter best = new BufferedWriter(new FileWriter(new File("antBest.txt")));
        long start = System.currentTimeMillis();
        try {
            BufferedReader read = new BufferedReader(new FileReader(new File("ants.txt")));


            String line;
            while ((line = read.readLine()) != null) {
                toRun.add(line);
            }
        } catch (FileNotFoundException e) {
        }
//        if (toRun.size() == 0) {
            for (int i = 0; i < 15; i++) {

                population.add(new Individual());
            }

  //      }
        while (true) {
            byte[] receiveData = new byte[1024];
            byte[] sendData = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            serverSocket.receive(receivePacket);
            String sentence = new String(receivePacket.getData());
            sentence = sentence.trim();

            if (sentence.equals(ASK_FOR_WORK)) {
                String changed = "";
                double[] vals;
                System.out.println("recieved work request");
                if (toRun.size() > 0) {
                    System.out.println("adding from queue");
                    changed = toRun.get(0);
                    toRun.remove(0);
                } else {
                    System.out.println("making new");
                    double rand = Math.random();
                    if (rand < .4) {
                        vals = population.get((int) (Math.random() * (population.size()-1))).mutateGenes();
                    } else if (rand < .8) {
                        vals = population.get((int) (Math.random() * (population.size()-1))).crossoverGenes(population.get((int) (Math.random() * (population.size()-1))).getValues());
                    } else if (rand < .9) {
                        toRun.add(Arrays.toString(population.get(0).getValues()));
                        toRun.add(Arrays.toString(population.get(0).getValues()));
                        vals = population.get(0).getValues();
                        if (population.size() > 2) {
                            population.remove(0);
                        }
                    } else {
                        toRun.add(Arrays.toString(population.get(1).getValues()));
                        toRun.add(Arrays.toString(population.get(1).getValues()));
                        vals = population.get(1).getValues();
                        if (population.size() > 2) {
                            population.remove(1);
                        }
                    }

                    changed = Arrays.toString(vals);
                }
                System.out.println("sending work" + changed);

                InetAddress IPAddress = receivePacket.getAddress();
                int port = receivePacket.getPort();



                sendData = changed.getBytes();
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
                serverSocket.send(sendPacket);
            } else {

                System.out.println("reporting values:" + sentence);
                sentence = sentence.replace("[", "").replace("]", "");
                Individual ind = new Individual(sentence);
                stats.write("" + (System.currentTimeMillis() - start) + ":" + ind.getFitness() + "\n");
                stats.flush();
                best.write("" + (System.currentTimeMillis() - start) + ":" + population.get(0).getFitness() + "\n");
                best.flush();

                population.add(ind);
                Collections.sort(population);
                if (population.size() > populationSize * 2) {
                    List<Individual> newPop = new ArrayList();
                    newPop.addAll(population.subList(0, populationSize));
                    population = newPop;



                    BufferedWriter write = new BufferedWriter(new FileWriter(new File("ants.txt")));
                    for (Individual i1 : population) {
                        write.write(Arrays.toString(i1.getValues()) + "\n");
                    }
                    write.flush();
                    write.close();
                    System.out.println("saved");
                }
                System.out.println("best: " + population.get(0).getFitness() + ":" + Arrays.toString(population.get(0).getValues()));

            }
        }
    }
}
